#include "include.h"
#include "func.h"
#include "func_bt.h"

#define MAX_DIG_VAL             32767
#define AEC_DIG_P0DB            (MAX_DIG_VAL * 1.000000)
#define AEC_DIG_P1DB            (MAX_DIG_VAL * 1.122018)
#define AEC_DIG_P2DB            (MAX_DIG_VAL * 1.258925)
#define AEC_DIG_P3DB            (MAX_DIG_VAL * 1.412538)
#define AEC_DIG_P4DB            (MAX_DIG_VAL * 1.584893)
#define AEC_DIG_P5DB            (MAX_DIG_VAL * 1.778279)
#define AEC_DIG_P6DB            (MAX_DIG_VAL * 1.995262)
#define AEC_DIG_P7DB            (MAX_DIG_VAL * 2.238721)
#define AEC_DIG_P8DB            (MAX_DIG_VAL * 2.511886)
#define AEC_DIG_P9DB            (MAX_DIG_VAL * 2.818383)

typedef struct {
    //AEC
    u8 aec_en       :   1;
    u8 aec_fix      :   1;      //优化回声消除算法（主频48MHz以上）
    u8 aec_resample :   1;      //MIC采用16KHz降采样
    u8 aec_echo_level;
    u8 aec_far_offset;
    //ALC
    u8 alc_en       :   1;
    u8 alc_fade_in_step;
    u8 alc_fade_out_step;
    u8 alc_fade_in_delay;
    u8 alc_fade_out_delay;
    s32 alc_far_voice_thr;
    //WNR
    u8 wnr_en       :   1;
    u8 near_dnr_floor_en   :   1;
    u8 far_nr_en    :   1;
    u8 src_en       :   1;

    //降噪
    u16 noise_threshoid;
	u8 near_nr_en;
} bt_voice_cfg_t;

static bt_voice_cfg_t bt_voice_cfg AT(.sco_data);
void bt_voice_init(bt_voice_cfg_t *p);
void bt_voice_exit(void);
void sdadc_set_digital_gain(u8 gain);
bool bt_tsco_is_en(void);
void bt_src_init(void);
bool sco_is_msbc_on(void);

void sco_huart_putcs(u8 type, const void *buf, uint len);
void ains2_process(s16 *data);
void ains2_init(u32 nt,u8 wind_level,u8 fre_mid_min, u8 fre_high_min);

#if BT_SCO_FAR_NR_EN || BT_SCO_AINS2_EN
static u8 bt_call_sysclk;
#endif

#if BT_AEC_EN
AT(.bt_voice.aec.offset)
u16 aec_far_add_offset(void)  //配置界面中的 AEC远端补偿值最大只有255,当实测远端补偿值超过255的部份,可以在这个函数中配置
{
    return 0;
}
#endif

const int mic_post_gain[10] = {
    0,
    AEC_DIG_P1DB,
    AEC_DIG_P2DB,
    AEC_DIG_P3DB,
    AEC_DIG_P4DB,
    AEC_DIG_P5DB,
    AEC_DIG_P6DB,
    AEC_DIG_P7DB,
    AEC_DIG_P8DB,
    AEC_DIG_P9DB,
};

#if BT_SCO_DBG_EN
extern const u8 btmic_ch_tbl[];
void sco_audio_set_param(u8 type, u16 value)
{
    printf("set param[%d]:%d\n", type, value);
    if (type == AEC_PARAM_NOISE) {
        f_bt.noise = value;
        bt_voice_cfg.noise_threshoid = value;
    } else if (type == AEC_PARAM_LEVEL) {
        f_bt.aec_level = value;
        bt_voice_cfg.aec_echo_level = value;
    } else if (type == AEC_PARAM_OFFSET) {
        f_bt.aec_offset = value;
        bt_voice_cfg.aec_far_offset = value;
    } else if (type == AEC_PARAM_MIC_ANL_GAIN) {
        f_bt.mic_anl_gain = value;
        set_mic_analog_gain(value, btmic_ch_tbl[xcfg_cb.bt_ch_mic]);
    } else if (type == AEC_PARAM_MIC_DIG_GAIN) {
        f_bt.mic_dig_gain = value;
        u8 channal = btmic_ch_tbl[xcfg_cb.bt_ch_mic];
        if (channal & 0x0f) {
            sdadc_set_digital_gain((u8)(value & 0x1f) | 0x40);
        } else {
            sdadc_set_digital_gain((u8)(value & 0x1f) | 0x80);
        }
    }
}
#endif

//库调用，设置MIC的增益（回声消除算法之后）
AT(.com_text.sco)
int sco_set_mic_gain_after_aec(void)
{
    return mic_post_gain[BT_SCO_MIC_POST_GAIN];
}

u16 cfg_nr_near_value(void)
{
    return BT_SCO_FAR_NOISE_THRESHOID;
}

u8 cfg_sco_far_nr_level(void)
{
    return BT_SCO_FAR_NR_LEVEL;
}

AT(.bt_voice.sco_dnr)
bool cfg_bt_sco_far_dnr_en(void)
{
    return BT_SCO_FAR_DNR_EN;
}


#if BT_SCO_MAV_EN
//魔音化
static s16 buf_01[2048];
static s16 buf_02[128];
static s16 buf_03[128];
static s16 buf_04[512];
static s16 buf_05[64];
static s16 buf_06[64];
static char buf_07[512];
u8 sys_sco_clk;
typedef struct {
    u8 res[2];
    s16 *buf_used;
    s16 *inbuf;
    s16 *outbuf;
    s16 *cache;
    s16 *mav_out;
    s16 *out1_buf;
    char *s8_fdata;
}mav_cfg_test;

mav_cfg_test mav_cfg_te = {
    .res[0]         = 0,
    .res[1]         = 0,
    .buf_used           = buf_01,
    .inbuf              = buf_02,
    .outbuf             = buf_03,
    .cache              = buf_04,
    .mav_out            = buf_05,
    .out1_buf           = buf_06,
    .s8_fdata           = buf_07,
};

#define MIC_CHCHE_LEN   512
struct mic_mav_cache_t {
    u16 wptr;
    u16 rptr;
    u16 optr;
    u16 len;
    u16 olen;
    s16 buf[MIC_CHCHE_LEN];
} mic_mav_cache AT(.sco_cache);

const u8 magic_table[4][2] = {
    {0, 5},
    {0, 2},
    {1, 1},
    {1, 4},
};

///魔音初始化
void sco_magic_config(void)
{
   magic_voice_init(&mav_cfg_te);
}

///切换魔音
void sco_magic_voice_switch(void)
{
    //设置魔音级别
    u8 magic_type,magic_level;
    static int magic_sel_ce = 0;
    magic_sel_ce++;
    if (magic_sel_ce > 4) {
        magic_sel_ce = 0;
    }

    if (!magic_sel_ce) {
        magic_type = 0;
        magic_level = 0;
    } else {
        magic_type = magic_table[magic_sel_ce - 1][0];
        magic_level = magic_table[magic_sel_ce - 1][1];
    }
    magic_voice_set_level(magic_type, magic_level);

}

void bt_sco_mav_process(u32 *ptr, u32 sample)
{
    u16 len = sample << 1;
    struct mic_mav_cache_t *p = &mic_mav_cache;
    if((MIC_CHCHE_LEN - p->wptr) >= sample){
        memcpy(&p->buf[p->wptr], ptr, len);
        p->wptr += sample;
        if(p->wptr >= MIC_CHCHE_LEN){
            p->wptr = 0;
        }
    } else {
        u16 remain = MIC_CHCHE_LEN - p->wptr;
        memcpy(&p->buf[p->wptr], ptr, remain * 2);
        memcpy(p->buf, &ptr[remain], (sample - remain) * 2);
        p->wptr = sample - remain;
    }
    p->len += sample;
    if(p->len >= 128){
        memcpy(mav_cfg_te.inbuf, &p->buf[p->rptr], 256);
        memcpy(&p->buf[p->rptr], mav_cfg_te.outbuf, 256);
        magic_voice_process();
        //mav_kick_start();

        p->rptr += 128;

        if (p->rptr >= MIC_CHCHE_LEN) {
            p->rptr = 0;
        }
        p->len -= 128;
        p->olen += 128;
    }
    if (p->olen >= sample) {
        if ((MIC_CHCHE_LEN - p->optr) >= sample) {
            memcpy(ptr, &p->buf[p->optr], len);
            p->optr += sample;
            if (p->optr >= MIC_CHCHE_LEN) {
                p->optr = 0;
            }
        } else {
            u16 remain = MIC_CHCHE_LEN - p->optr;
            memcpy(ptr, &p->buf[p->optr], remain * 2);
            memcpy(&ptr[remain], p->buf, (sample - remain) * 2);
            p->optr = sample - remain;
        }
        p->olen -= sample;
    }
}

#endif // BT_MIC_MAV_EN

#if FUNC_BT_EN
void sco_audio_init(void)
{
    printf("sco_audio_init\n");
    memset(&bt_voice_cfg, 0, sizeof(bt_voice_cfg_t));

#if FOT_EN
    fot_update_pause();
#endif

#if BT_SCO_DBG_EN
    bt_voice_cfg.noise_threshoid = f_bt.noise;
#else
    bt_voice_cfg.noise_threshoid = BT_NOISE_THRESHOID;
#endif

#if BT_AEC_EN || BT_ALC_EN
    if (xcfg_cb.bt_aec_en) {
#if BT_AEC_EN
        bt_voice_cfg.aec_en = 1;
    #if BT_SCO_DBG_EN
        bt_voice_cfg.aec_echo_level = f_bt.aec_level;
        bt_voice_cfg.aec_far_offset = f_bt.aec_offset;
    #else
        bt_voice_cfg.aec_echo_level = BT_ECHO_LEVEL;
        bt_voice_cfg.aec_far_offset = BT_FAR_OFFSET;
    #endif
#endif // BT_AEC_EN
    } else if (xcfg_cb.bt_alc_en) {
#if BT_ALC_EN
        bt_voice_cfg.alc_en = 1;
        bt_voice_cfg.alc_fade_in_delay = BT_ALC_FADE_IN_DELAY;
        bt_voice_cfg.alc_fade_in_step = BT_ALC_FADE_IN_STEP;
        bt_voice_cfg.alc_fade_out_delay = BT_ALC_FADE_OUT_DELAY;
        bt_voice_cfg.alc_fade_out_step = BT_ALC_FADE_OUT_STEP;
        bt_voice_cfg.alc_far_voice_thr = BT_ALC_VOICE_THR;
#endif // BT_ALC_EN
    }
#endif

#if BT_SCO_AINS2_EN
	bt_voice_cfg.near_nr_en = (BT_SCO_AINS2_EN << 3) | (BT_SCO_AINS2_MODE << 2);
	ains2_init(BT_SCO_AINS2_LEVEL, BT_SCO_AINS2_WIND, BT_FRE_MID_MIN, BT_FRE_HIGH_MIN);
	 bt_call_sysclk = get_cur_sysclk();

    if (bt_call_sysclk < SYS_120M) {
        set_sys_clk(SYS_120M);
    }
#endif

#if BT_SCO_FAR_NR_EN
    bt_voice_cfg.far_nr_en = BT_SCO_FAR_NR_EN;
#endif

#if BT_SCO_FAR_DNR_EN
    sco_far_dnr_level_init(BT_SCO_FAR_DNR_LEVEL);           //0~30
#endif

#if BT_SCO_SRC_EN
    bt_src_init();
    if (bt_tsco_is_en() && bt_tws_is_connected()) {
        bt_voice_cfg.src_en = 1;
    }
#endif
#if IIS_MASTER_RX_2_SCO_MIC
#if IIS_RX_2_SCO_SRC
void iis2bt_sco_sync_init(void);
    iis2bt_sco_sync_init();
#endif
    iis_start();
#endif // IIS_MASTER_RX_2_SCO_MIC
#if SYS_KARAOK_EN
    bsp_karaok_exit(AUDIO_PATH_KARAOK);
    sys_cb.hfp_karaok_en = BT_HFP_CALL_KARAOK_EN;       //通话是否支持KARAOK
    plugin_hfp_karaok_configure();
    if (sys_cb.hfp_karaok_en) {
        bsp_karaok_init(AUDIO_PATH_BTMIC, FUNC_BT);
        kara_sco_start();
    } else
#endif // SYS_KARAOK_EN
    {
        bt_voice_init(&bt_voice_cfg);
        dac_set_anl_offset(1);
#if !IIS_MASTER_RX_2_SCO_MIC || IIS_RX_2_SCO_SRC
        audio_path_init(AUDIO_PATH_BTMIC);
        audio_path_start(AUDIO_PATH_BTMIC);
#endif
        bsp_change_volume(sys_cb.hfp_vol * sys_cb.hfp2sys_mul);
        dac_fade_in();
    }

#if BT_HFP_REC_EN
    bt_sco_rec_init();
    f_bt.music_rec_disable = 1;
#endif

#if DMA_OUT_I2S_SEL == I2S_DMA_BT && I2S_EN
    bsp_i2s_init();
#endif
}

void sco_audio_exit(void)
{
    f_bt.music_rec_disable = 0;
    printf("sco_audio_exit\n");
#if BT_HFP_REC_EN
    sfunc_record_stop();
#endif

#if SYS_KARAOK_EN
    if (sys_cb.hfp_karaok_en) {
        kara_sco_stop();
        bsp_karaok_exit(AUDIO_PATH_BTMIC);
        sys_cb.hfp_karaok_en = 0;
    } else
#endif // SYS_KARAOK_EN
    {
        dac_fade_out();
        dac_set_anl_offset(0);
        bsp_change_volume(sys_cb.vol);
        audio_path_exit(AUDIO_PATH_BTMIC);
        #if DMA_OUT_I2S_SEL == I2S_DMA_BT && I2S_EN
        bsp_i2s_exit();
        #endif
        bt_voice_exit();
    }
#if SYS_KARAOK_EN
    bsp_karaok_init(AUDIO_PATH_KARAOK, FUNC_BT);
#endif

#if BT_SCO_FAR_NR_EN || BT_SCO_AINS2_EN
    set_sys_clk(bt_call_sysclk);
#endif

#if BT_REC_EN && BT_HFP_REC_EN
    bt_music_rec_init();
#endif

#if FOT_EN
    fot_update_continue();
#endif
}

static void sfunc_bt_call_process(void)
{
    func_process();
    func_bt_status();
}

#if IIS_MASTER_RX_2_SCO_MIC
#define IIS_DMA_SAMPLES  32

#if IIS_RX_2_SCO_SRC
AT(.com_text.iis_sco)
u8 get_i2s_samples(void)
{
    return IIS_DMA_SAMPLES;
}
#endif
AT(.com_text.iis_sco_cst)
const char str_iisrx_info_scomic[] = "IISRX: samples = %d, isrcnt = %d (SR_%d)\n";

void lc_sco_set_hci_rx(u16 *ptr, u32 samples);
void bt_sco_process(u8 *buf, u32 samples);
void src_kick_start(u8 * buf);

u16 scomic_buf[32];    //16K-->8K 缓存buf

AT(.com_text.iis_sco)
void iis_2_scomic(void *buf, u32 samples, bool iis_32bit)
{
    u32 *ptr32 = (u32*)buf;
    u16 *ptr16 = (u16*)buf;
    if (iis_32bit) {  //IIS_32BIT
        samples = samples / 2;
        for (int i = 0; i < samples; i++) {  //32BIT ->16bit  for dac out
           ptr16[2*i] =  (u16)(ptr32[2*i] >> 16);
           ptr16[2*i+1] =  (u16)(ptr32[2*i+1] >> 16);
        }
    }
    //dual ->mono
    for(int i = 0; i < samples; i++) {
        ptr16[i] = ptr16[2*i];
    }
#if 0
    static u32 ticks = 0;
    static u32 isr_cnt = 0;
    isr_cnt++;
    if (tick_check_expire(ticks,1000)) {
        printk(str_iisrx_info_scomic,samples, isr_cnt, samples*isr_cnt);
        isr_cnt = 0;
        ticks = tick_get();
    }
#endif
    static u32 cnt = 0;
#if IIS_RX_2_SCO_SRC
    if(!sco_is_msbc_on()) {
        for(int i = 0; i < 32/2; i++) {
            scomic_buf[i + cnt*32/2] = ptr16[2*i];    //16K-->8K
        }
        cnt++;
        if(cnt >= 2) {
            src_kick_start((u8 *)scomic_buf);
            cnt = 0;
        }
    }
    else {
        src_kick_start((u8 *)buf);
    }
#else
    if(!sco_is_msbc_on()) {
        for(int i = 0; i < 32/2; i++) {
            scomic_buf[i + cnt*32/2] = ptr16[2*i];    //16K-->8K
        }
        cnt++;
        if(cnt >= 2) {
            lc_sco_set_hci_rx(scomic_buf, samples);
            cnt = 0;
        }
    }
    else {
        lc_sco_set_hci_rx(buf, samples);
    }
#endif // IIS_RX_2_SCO_SRC
}

#define IIS_DMABUF_LEN   (IIS_DMA_SAMPLES * 2 * 2 *4)               //tx,rx double_buf, one_sample_4byte
u8 iis_sco_dmabuf[IIS_DMABUF_LEN];                               //若iis_cfg.mode中有RAMTX或RAMRX,需要该dmabuf做中断缓存
void iis2scomic_init(void)                                          //iis初始化, 需要在dac_init之后调用
{
    static iis_cfg_t iis2scomic_cfg;
    memset(&iis2scomic_cfg,0x00, sizeof(iis2scomic_cfg));
    iis2scomic_cfg.mode        = IIS_SLAVE_RAMRX;
    iis2scomic_cfg.iomap       = IIS_G1;
    iis2scomic_cfg.bit_mode    = IIS_32BIT;
    iis2scomic_cfg.data_mode   = IIS_DATA_NORMAL;
    iis2scomic_cfg.mclk_sel    = IIS_MCLK_256FS;
    iis2scomic_cfg.mclk_out_en = IIS_MCLK_OUT_DIS;
    if (iis2scomic_cfg.mode & IISCFG_DMA) {
        printf("iis_dma config run\n");
        iis2scomic_cfg.dma_cfg.samples = IIS_DMA_SAMPLES;
        iis2scomic_cfg.dma_cfg.dmabuf_ptr = iis_sco_dmabuf;
        iis2scomic_cfg.dma_cfg.dmabuf_len = IIS_DMABUF_LEN;
        iis2scomic_cfg.dma_cfg.iis_isr_rx_callbck = iis_2_scomic;  //iis_rx接收完一个DMA后起中断,回调该函数,可以从buf中取出接收到数据
        iis2scomic_cfg.dma_cfg.iis_isr_tx_callbck = NULL;          //iis_tx发送完一个DMA后起中断,要求向buf中填入数据,以备下一次发送
    }
    iis_cfg_init(&iis2scomic_cfg);
}
#endif  //IIS_MASTER_RX_2_SCO_MIC

static void sfunc_bt_call_enter(void)
{
#if BT_AEC_DUMP_EN || BT_ALC_DUMP_EN
    dump_buf_huart_init();
#endif
#if BT_SCO_MAV_EN
    sys_sco_clk = get_cur_sysclk();
    if (sys_sco_clk != SYS_120M){
        set_sys_clk(SYS_120M);  //提高主频
    }
#endif // BT_SCO_MAV_EN
    //bsp_bt_get_remote_phone_number();   //IOS 手机响铃时马上接起，可能得不到远端号码， 这里可以重新去获取一次
}

static void sfunc_bt_call_exit(void)
{
#if IIS_MASTER_RX_2_SCO_MIC
    iis_stop();
#endif
#if BT_SCO_MAV_EN
    set_sys_clk(sys_sco_clk);
#endif
    bsp_change_volume(sys_cb.vol);
}

#if BT_AEC_DUMP_EN   //AEC_DATA_DUMP
u8 sco_dump_dma_buf[14 + 256 + 14 + 128];   //AEC前(双声道:近端放在左声道 + 远端放在右声道)和 AEC后数据(单声道)
AT(.bt_voice.aec)
void aec_dump(u16 *near, u16 *far, u16 *out)
{
    u32 *aec_in_buf;
    void *aec_out_buf = out;
    dump_dma_wait();
    aec_in_buf = (u32*)&sco_dump_dma_buf[14];
    for(int i = 0; i < 64; i++) {
        aec_in_buf[i] = (far[i] << 16) | near[i];
    }
    dump_put2ram(&sco_dump_dma_buf[0],aec_in_buf,256,1);
    dump_put2ram(&sco_dump_dma_buf[14 + 256],aec_out_buf,128,2);
    dump_dma_kick(sco_dump_dma_buf,14 + 256 + 14 + 128);
};
#endif

//降噪算法调用
AT(.bt_voice.ans)
void sco_ns_process(s16 *data)
{
#if BT_AEC_DUMP_EN
    dump_dma_wait();
    dump_put2ram(&sco_dump_dma_buf[0],data,128,0);
    dump_dma_kick(sco_dump_dma_buf,14 + 128);
#endif
#if BT_SCO_AINS2_EN
	ains2_process(data);
#endif
}

#if BT_ALC_DUMP_EN
//file_0(双声道): L(远端数据(提取远端能量进行仲裁) + R 近端最终处理完后的数据
//file_1(双声道): L(MIC降噪前的数据) + R(MIC降噪后的数据)
//file_2(单声道): ALC 仲裁后的MIC近端数据
u8 sco_dump_dma_buf[14+256 + 14+256 + 14+128];
AT(.bt_voice.alc)
void alc_dump(void *buf, int idx)
{
    u16 *pcml,*pcmr;
    u32 *pcm_dual;
   // printf("[%d]",idx);
#if  1   //近端ALC,近端降噪分析
    if(0 == idx) {          //0: 远端数据(提取远端能量进行仲裁)
         memcpy(&sco_dump_dma_buf[14+128],buf,128);
    } else if (1 == idx) {  //1: 近端最终处理完后的数据
        //0和1合并成双声道一起导出，方便查看远端数据能量 对近端MIC进入淡入淡出的效果
        pcml = (u16*)&sco_dump_dma_buf[14+128];
        pcmr = (u16*)buf;
        pcm_dual = (u32*)&sco_dump_dma_buf[14];
        for(int i = 0; i < 64; i++) {
            pcm_dual[i] = ((u32)pcmr[i] << 16) | pcml[i];
        }
        dump_put2ram(&sco_dump_dma_buf[0],pcm_dual,256,0);             //file_0(双声道): L(远端数据(提取远端能量进行仲裁) + R 近端最终处理完后的数据
        dump_dma_wait();
        dump_dma_kick(sco_dump_dma_buf,14+256);  //0/1一起KICK导出
    } else if (2 == idx) {     //2: MIC原始数据
        memcpy(&sco_dump_dma_buf[14+256 + 14+128],buf,128);
    } else if (3 == idx) {     //3: MIC降噪后的数据
        //2和3合并成双声道一起导出,方便查看降噪效果
        pcml = (u16*)&sco_dump_dma_buf[14+256 + 14+128];
        pcmr = (u16*)buf;
        pcm_dual = (u32*)&sco_dump_dma_buf[14+256 + 14];
        for(int i = 0; i < 64; i++) {
            pcm_dual[i] = ((u32)pcmr[i] << 16) | pcml[i];
        }
        dump_put2ram(&sco_dump_dma_buf[14+256],pcm_dual,256,1);        //file_1(双声道): L(MIC降噪前的数据) + R(MIC降噪后的数据)
    } else if (4 == idx) {  //4: MIC ALC仲裁后的数据 (后面还会增加MIC后置增益,在idx=1中导出)
        dump_put2ram(&sco_dump_dma_buf[(14+256)*2], buf, 128, 2);      //file_2(单声道): ALC 仲裁后的MIC近端数据
        dump_dma_wait();
        dump_dma_kick(&sco_dump_dma_buf[14+256], (14+256 + 14+128));   //2/3/4 一起KICK导出
    }
#else  //远端降噪分析
    if(10 == idx) {          //10: 远端数据(降噪前)
        memcpy(&sco_dump_dma_buf[14+128],buf,128);
    } else if(11 == idx) {  //11: 远端数据(降噪后)
        //0和1合并成双声道一起导出，方便查看远端降噪前和降噪后的效果
        pcml = (u16*)&sco_dump_dma_buf[14+128];
        pcmr = (u16*)buf;
        pcm_dual = (u32*)&sco_dump_dma_buf[14];
        for(int i = 0; i < 64; i++) {
            pcm_dual[i] = ((u32)pcmr[i] << 16) | pcml[i];
        }
        dump_put2ram(&sco_dump_dma_buf[0],pcm_dual,256,0);             //file_3(双声道): L(远端数据(降噪前) + R(远端数据(降噪后)
        dump_dma_wait();
        dump_dma_kick(sco_dump_dma_buf,14+256);
    }

#endif
};
#endif


void dump_buf_huart_init(void);

AT(.text.func.bt)
void sfunc_bt_call(void)
{
    printf("%s\n", __func__);
    sfunc_bt_call_enter();
#if DAC_DNR_EN
    u8 sta = dac_dnr_get_sta();
    dac_dnr_set_sta(0);
#endif

#if SYS_KARAOK_EN
    u8 rm_sta = karaok_get_voice_rm_sta();
    karaok_voice_rm_disable();
#endif // SYS_KARAOK_EN

    while ((f_bt.disp_status >= BT_STA_OUTGOING) && (func_cb.sta == FUNC_BT)) {
        sfunc_bt_call_process();
        sfunc_bt_call_message(msg_dequeue());
        func_bt_display();
    }

#if SYS_KARAOK_EN
    if (rm_sta) {
        karaok_voice_rm_enable();
    }
#endif // SYS_KARAOK_EN

#if DAC_DNR_EN
    dac_dnr_set_sta(sta);
#endif
    sfunc_bt_call_exit();
}
#else

void sco_audio_init(void){}
void sco_audio_exit(void){}

#endif //FUNC_BT_EN


//修复苹果手机通话挂断后的“嘟嘟”声有卡顿
//bool bt_stutas_is_play(void)
//{
//    if(f_bt.disp_status >= BT_STA_PLAYING)
//        return true;
//    else
//        return false;
//}

